package com.jojo.intermediate.day5_array;

import java.util.HashMap;

/**
 * 560、和为K的子数组
 *
 * 给你一个整数数组 nums 和一个整数 k ，请你统计并返回 该数组中和为 k 的连续子数组的个数 。
 *
 * 示例 1：
 * 输入：nums = [1,1,1], k = 2
 * 输出：2
 *
 * 示例 2：
 * 输入：nums = [1,2,3], k = 3
 * 输出：2
 */
public class SumKSubArray {

    /** myCode 枚举法（O(n^2)） */
    public int subarraySum(int[] nums, int k) {
        int n = nums.length;
        int count = 0;
        for (int i = 0;i < n;i++){
            int sum = 0;
            for (int j = i;j < n;j++){
                sum = sum + nums[j];
                if (sum == k){
                    count++;
                }
            }
        }
        return count;
    }

    /** pe.前缀和 + 哈希表 */
    public int subarraySum2(int[] nums, int k) {
        // hash
        // 记录合适的连续字符串数量
        int count=0;
        // 记录前面数字相加之和
        int pre=0;
        // map记录前几个数字之和为K出现相同和的次数为V
        HashMap<Integer,Integer> map = new HashMap<>();
        // 初始化
        map.put(0,1);
        for (int num : nums) {
            pre += num;
            // 前缀和
            // 设
            // pre[i]=pre[i−1]+nums[i]
            // 由于补上了0，1这个情况 问题由多少个连续数字之和等于k 转为
            // pre[i]−pre[j−1]==k （前缀和之差为k，代表这两个前缀和中间的数字相加就是K）
            // 如果前面某些数字之和加上这个数字正好等于K（存在一个数字加上nums[i]结果为K
            // 说明找到了
            if (map.containsKey(pre - k)) {
                // 累计
                count += map.get(pre - k);
            }
            // 计算新的和放入map
            map.put(pre, map.getOrDefault(pre, 0) + 1);
        }
        return count;
    }

    public static void main(String[] args) {
        SumKSubArray k = new SumKSubArray();
        int[] arr = {1,2,3};
        int i = k.subarraySum2(arr, 3);
        System.out.println(i);
    }
}
